package br.uece.laconi.tac.fuzzy;

import br.uece.laconi.tac.fuzzy.functions.GenericFunction;

public class MamdaniController extends FuzzyController {

	@Override
	//public TriangleFuzzyNumber calculateOutput() {
	public FuzzySet calculateOutput() {
				if(alpha.size() != z.size()) return null;
		
		GenericFunction func = new GenericFunction(){
			public Float calculate(float[] var) {
				float x = var[0];
				float result = Float.MIN_VALUE;
				for (int i=0; i < alpha.size(); i++) {
					float alphaValue = ((CrispFuzzyNumber)alpha.get(i)).value;
					float zDegree = z.get(i).membershipDegree(x);
					result = Math.max(result, Math.min(alphaValue, zDegree));
				}
				return result;
			}};
		FuzzySet composedFuzzy = new FuzzySet(func);
		
		// Calculate domain interval
		float max = Float.MIN_VALUE;
		float min = Float.MAX_VALUE;
		for (FuzzyNumber number : z) {
			max = Math.max(max, number.interval[1]);
			min = Math.min(min, number.interval[0]);
		}
		
		float coa = defuzzyfication(composedFuzzy, min, max);
		TriangleFuzzyNumber aux = (TriangleFuzzyNumber)z.get(0);	
		return new TriangleFuzzyNumber(coa, aux.leftSpread, aux.rightSpread);
//		return composedFuzzy;
	}
	
	private float defuzzyfication(FuzzySet fuzzyset, float domainMin, float domainMax) {
		//Defuzzyfication with Center of Area Method (COA)
		float STEP = 0.01f;
		float coa_sum1 = 0f; 
		float coa_sum2 = 0f; 
		for (float i=domainMin; i<=domainMax; i+= STEP) {
			coa_sum1 += fuzzyset.membershipDegree(i)*i;
			coa_sum2 += fuzzyset.membershipDegree(i);
		}
		float coa = coa_sum1 / coa_sum2;
		return coa;
	}
}
